package demo.service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;

/**
 * ElasticSearch计划7.X移出type,不再有type的操作,所有本文中将type和Index名称设置为相同的名字.
 * 
 * @author hanjy
 *
 */
// @Service
public class ElasticSearchService {

    @Autowired
    private RestHighLevelClient rhlClient;

    /**
     * 添加Index 由于使用RestHighLevelClient（后称为rhlClient）时，进行Index操作，所有IndexRequest都会校验Index，type，source，contentType不为空。
     * 
     * 所有构建创建Index创建请求时需要将Index，type，source，contentType配置完整
     * 
     * 因为整合了ik中文分词器，所以“analyzer”: “ik_max_word”此处参考安装配置ik分词器
     * 
     * @return
     */
    public boolean indexCreate() {
        try {
            CreateIndexRequest index = new CreateIndexRequest("index_name");
            Map<String, Object> properties = new HashMap<>();
            Map<String, Object> propertie = new HashMap<>();
            propertie.put("type", "text");
            propertie.put("index", true);
            propertie.put("analyzer", "ik_max_word");

            properties.put("field_name", propertie);

            XContentBuilder builder = JsonXContent.contentBuilder();
            builder.startObject().startObject("mappings").startObject("index_name").field("properties", properties)
                    .endObject().endObject().startObject("settings").field("number_of_shards", 3)
                    .field("number_of_replicas", 1).endObject().endObject();
            index.source(builder);
            rhlClient.indices().create(index);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }

    }

    /**
     * 判断Index是否存在
     * 
     * @param indexName
     * @return
     */
    public boolean indexExists(String indexName) {
        GetIndexRequest request = new GetIndexRequest();
        request.indices(indexName);
        try {
            return rhlClient.indices().exists(request);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除Index
     * 
     * @param indexName
     * @return
     */
    public boolean deleteIndex(String indexName) {
        DeleteIndexRequest index = new DeleteIndexRequest(indexName);
        try {
            rhlClient.indices().delete(index);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }

    }

    /**
     * @param keyword1
     *            关键字1
     * @param keyword2
     *            关键字2
     * @param startDate
     *            起始时间
     * @param endDate
     *            终止时间
     *
     **/
    public SearchResponse pageQueryRequest(String keyword1, String keyword2, String startDate, String endDate,
            int start, int size) {

        // 这个sourcebuilder就类似于查询语句中最外层的部分。包括查询分页的起始，
        // 查询语句的核心，查询结果的排序，查询结果截取部分返回等一系列配置
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 结果开始处
        sourceBuilder.from(start);
        // 查询结果终止处
        sourceBuilder.size(size);
        // 查询的等待时间
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        MatchQueryBuilder matchbuilder = QueryBuilders.matchQuery("message", keyword1 + " " + keyword2);
        // 同时满足两个关键字
        matchbuilder.operator(Operator.AND);
        // 查询在时间区间范围内的结果
        RangeQueryBuilder rangbuilder = QueryBuilders.rangeQuery("date");
        if (!"".equals(startDate)) {
            rangbuilder.gte(startDate);
        }
        if (!"".equals(endDate)) {
            rangbuilder.lte(endDate);
        }
        // 等同于bool，将两个查询合并
        BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
        boolBuilder.must(matchbuilder);
        boolBuilder.must(rangbuilder);
        // 排序
        FieldSortBuilder fsb = SortBuilders.fieldSort("date");
        fsb.order(SortOrder.DESC);
        sourceBuilder.sort(fsb);

        sourceBuilder.query(boolBuilder);
        // System.out.println(sourceBuilder);
        SearchRequest searchRequest = new SearchRequest("request");
        searchRequest.types("doc");
        searchRequest.source(sourceBuilder);
        SearchResponse response = null;
        try {
            response = rhlClient.search(searchRequest);
            SearchHits hits = response.getHits();
            int totalRecordNum = (int) hits.getTotalHits();
            for (SearchHit searchHit : hits) {
                Map<String, Object> source = searchHit.getSourceAsMap();
                JSONObject json = new JSONObject(source);
                System.out.println(json);
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return response;
    }

    public void delete(String index, String type, String deleteText) {
        try {
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            sourceBuilder.timeout(new TimeValue(2, TimeUnit.SECONDS));
            TermQueryBuilder termQueryBuilder1 = QueryBuilders.termQuery("content.keyword", deleteText);
            sourceBuilder.query(termQueryBuilder1);
            SearchRequest searchRequest = new SearchRequest(index);
            searchRequest.types(type);
            searchRequest.source(sourceBuilder);
            SearchResponse response = rhlClient.search(searchRequest);
            SearchHits hits = response.getHits();
            List<String> docIds = new ArrayList<>(hits.getHits().length);
            for (SearchHit hit : hits) {
                docIds.add(hit.getId());
            }

            BulkRequest bulkRequest = new BulkRequest();
            for (String id : docIds) {
                DeleteRequest deleteRequest = new DeleteRequest(index, type, id);
                bulkRequest.add(deleteRequest);
            }
            rhlClient.bulk(bulkRequest);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}
